<?php    
    use SharedPHP\UnitConverter;
        
    class TrainingProgramControl extends Control {
        protected static $_callable = array(
            "delete",
            "load",
            "save",
            "search",
            "schedule"
        );
        
        /**
         * Funktio poistaa harjoitusohjelman tiedot tietokannasta.
         *
         * @return bool
         */
        public static function delete($data) {
            $result = false;
            
            DB::begin();
            
            try {
                $tp = new TrainingProgramModel(array(
                    "hashid" => arrGet($data,"hashid")
                ));
                
                # Tarkasta onko harjoitusohjelma liitetty harjoituksiin
                $query = DB::preparedQuery("
                    SELECT id
                    FROM workout
                    WHERE training_programid=:tpid
                    LIMIT 1
                ",array(
                    "tpid" => $tp->id
                ));
                if (DB::numRows($query) == 1) {
                    DB::freeResult($query);
                    throw new DBException(
                        "Training program is attached to one or more workouts",
                        40,
                        __CLASS__,
                        "Training program is attached to one or more workouts"
                    );
                }
                
                $tp->delete();
                
                $result = true;
            } catch (Exception $e) {
                DB::rollback();
                throw $e;
            }
            
            DB::commit();
            
            return $result;
        }
        
        /**
         * Funktio hakee harjoitusohjelman tiedot tietokannasta.
         *
         * @return  array
         */
        public static function load($data) {
            $result = array();
            
            $tp = new TrainingProgramModel(array(
                "hashid" => arrGet($data,"hashid")
            ));
            
            # Harjoitusohjelman perustiedot
            $result["hashid"]           = $tp->hashid;
            $result["program_name"]     = $tp->program_name;
            $result["startdate"]        = $tp->startdate;
            $result["enddate"]          = $tp->enddate;
            $result["workout_count"]    = count($tp->training_program_schedule);
            $result["updated"]          = $tp->updated;
            $result["rowstamp"]         = $tp->rowstamp;
            
            # Templatet
            $result["templatelink"] = array();
            foreach ((array)$tp->training_program_template_link as $link) {
                $template = new TemplateModel($link->templateid);
                
                $result["templatelink"][] = array(
                    "templatehashid"        => $template->hashid,
                    "template_extratext"    => $template->extratext,
                    "days_to_next_workout"  => $link->days_to_next_workout
                );
            }
            
            # Merkinnät
            $result["records"] = array();
            foreach ((array)$tp->training_program_record as $record) {
                $result["records"][] = array(
                    "record" => $record->record
                );
            }
            
            return $result;
        }
        
        /**
         * Tallentaa harjoitusohjelman tiedot ja palauttaa ohjelman hashid:n.
         *
         * @param   array   $data   Tiedot
         * @return  string
         */
        public static function save($data) {
            DB::begin();
            
            try {
                $arr = null;
                $hashid = arrGet($data,"hashid");
                if (isset($hashid)) {
                    $arr = array("hashid" => $hashid);
                }
                
                $tp = new TrainingProgramModel($arr);
                
                # Aseta userid jos luodaan uutta
                if (!isset($hashid)) {
                    $tp->userid         = LoginControl::get("userid");
                    $tp->from_userid    = LoginControl::get("userid");
                    $tp->accepted       = date("Y-m-d H:i:s");
                } else {
                    # Poista muokkauksen yhteydessa vanhat alitietueet
                    $tp->deleteChilds();
                    $tp->unsetChilds();
                    
                    # Aseta päivitysaika
                    $tp->updated = date("Y-m-d H:i:s");
                }
                
                $tp->program_name   = $data;
                $tp->startdate      = $data;
                $tp->enddate        = $data;
                
                # Templatet
                $c = 0;
                foreach ((array)arrGet($data,"templatelink") as $link) {
                    RequestHandler::addIteration("TrainingProgramTemplateLinkModel");
                    
                    $tpLink = new TrainingProgramTemplateLinkModel();
                    
                    $tpLink->templateid = (new TemplateModel(array(
                        "hashid" => arrGet($link,"templatehashid")
                    )))->id;
                    $tpLink->days_to_next_workout = $link;
                    
                    $tp->training_program_template_link = $tpLink;
                    
                    if (++$c >= 100) {
                        break;
                    }
                }
                RequestHandler::clearIteration("TrainingProgramTemplateLinkModel");
                   
                # Merkinnät
                $c = 0;
                foreach ((array)arrGet($data,"records") as $record) {
                    RequestHandler::addIteration("TrainingProgramRecordModel");
                    if (mb_strlen(arrGet($record,"record","")) > 0) {
                        $rcd = new TrainingProgramRecordModel();
                        $rcd->record = $record;
                        
                        $tp->training_program_record = $rcd;
                        
                        if (++$c >= 100) {
                            break;
                        }
                    }
                }
                RequestHandler::clearIteration("TrainingProgramRecordModel");
                
                $tp->write();
                $hashid = $tp->hashid;
                
                # Muodosta aikataulu
                $links = $tp->training_program_template_link;
                $count = count($links);
                if ($count > 0) {
                    $workoutDate = strtotime($tp->startdate);
                    $enddate = strtotime($tp->enddate);
                    
                    $c = 0;
                    $pos = 0;
                    while ($workoutDate <= $enddate) {
                        $tps = new TrainingProgramScheduleModel();
                        $tps->training_programid    = $tp->id;
                        $tps->templateid            = $links[$pos]->templateid;
                        $tps->workout_date          = date("Y-m-d",$workoutDate);
                        $tps->write();
                        
                        # Lisää päiviä eteenpäin
                        $tmp = strtotime("+{$links[$pos]->days_to_next_workout} days",$workoutDate);
                        if ($tmp <= $workoutDate && ++$c >= 100) {
                            break;
                        }
                        $workoutDate = $tmp;

                        if (++$pos == $count) {
                            $pos = 0;
                        }
                    }
                }
            } catch (Exception $e) {
                DB::rollback();
                throw $e;
            }
            
            DB::commit();
            
            return $hashid;
        }
        
        /**
         * Etsii harjoitusohjelmien harjoituspäiviä tietokannasta (maksimissaan 10 000 kpl).
         *
         * @param   array   $data   Hakuparametrit
         * @return  array
         */
        public static function schedule($data) {
            $result = array(                
                "list"          => array(),
                "totalCount"    => 0
            );            
            
            $params = array(
                "userid" => LoginControl::get("userid")
            );
            $where = "";
            
            # Alkupvm
            if (isset($data["startdate"]) && $data["startdate"]) {
                $d = DateTime::createFromFormat("Y-m-d",$data["startdate"]);
                if ($d) {
                    $params["startdate"] = $d->format("Y-m-d");
                    $where .= " AND training_program_schedule.workout_date>=:startdate";
                }
            }
            
            # Loppupvm
            if (isset($data["enddate"]) && $data["enddate"]) {
                $d = DateTime::createFromFormat("Y-m-d",$data["enddate"]);
                if ($d) {
                    $params["enddate"] = $d->format("Y-m-d");
                    $where .= " AND training_program_schedule.workout_date<=:enddate";
                }
            }
            
            # Harjoituspohjan hashid
            if (isset($data["templatehashid"]) && $data["templatehashid"]) {
                $params["templatehashid"] = $data["templatehashid"];
                $where .= " AND template.hashid IN (:templatehashid)";
            }
            
            # Positio ja haettavien rivien määrä
            $pos = 0;
            $count = null;
            if (isset($data["pos"]) && (int)$data["pos"] >= 0) {
                $pos = (int)$data["pos"]; 
            }
            if (isset($data["count"])) {
                $count = (int)$data["count"];
                if ($count <= 0) {
                    return $result;
                }
            }
            
            # Suorita haku
            $query = DB::preparedQuery("
                SELECT training_program.hashid,
                  training_program.program_name,
                  template.hashid AS templatehashid,
                  template.extratext AS template_extratext,
                  training_program_schedule.workout_date
                FROM training_program
                INNER JOIN training_program_schedule ON
                  training_program_schedule.training_programid = training_program.id
                INNER JOIN template ON
                  template.id = training_program_schedule.templateid
                WHERE training_program.userid=:userid{$where}
                ORDER BY training_program_schedule.workout_date,
                  training_program.id,
                  training_program_schedule.id
                LIMIT 10000
                ",$params
            );
            $numrows = DB::numRows($query);
            if ($numrows > 0) {
                if (!isset($count)) {
                    $count = $numrows-$pos;
                }
                
                if ($count > 0) {
                    if ($pos > 0) {
                        DB::dataSeek($query,$pos);
                    }
                    
                    $c = 0;
                    while ($row = DB::fetchAssoc($query)) {
                        $result["list"][] = $row;
                        if (++$c >= $count) {
                            break;
                        }
                    }
                }
                DB::freeResult($query);
                
                $result["totalCount"] = $numrows;
            }
            
            return $result;
        }
        
        /**
         * Etsii harjoitusohjelmia tietokannasta (maksimissaan 10 000 kpl).
         *
         * @param   array   $data   Hakuparametrit
         * @return  array
         */
        public static function search($data) {
            $result = array(                
                "list"          => array(),
                "totalCount"    => 0
            );            
            
            $params = array(
                "userid" => LoginControl::get("userid")
            );
            $where = "";
            
            # Alkupvm
            if (isset($data["startdate"]) && $data["startdate"]) {
                $d = DateTime::createFromFormat("Y-m-d",$data["startdate"]);
                if ($d) {
                    $params["startdate"] = $d->format("Y-m-d");
                    $where .= " AND training_program.startdate<=:startdate";
                }
            }
            
            # Loppupvm
            if (isset($data["enddate"]) && $data["enddate"]) {
                $d = DateTime::createFromFormat("Y-m-d",$data["enddate"]);
                if ($d) {
                    $params["enddate"] = $d->format("Y-m-d");
                    $where .= " AND training_program.enddate>=:enddate";
                }
            }
            
            # Harjoituspohjan hashid
            if (isset($data["templatehashid"]) && $data["templatehashid"]) {
                $params["templatehashid"] = $data["templatehashid"];
                $where .= " AND template.hashid IN (:templatehashid)";
            }
               
            # Positio ja haettavien rivien määrä
            $pos = 0;
            $count = null;
            if (isset($data["pos"]) && (int)$data["pos"] >= 0) {
                $pos = (int)$data["pos"]; 
            }
            if (isset($data["count"])) {
                $count = (int)$data["count"];
                if ($count <= 0) {
                    return $result;
                }
            }
            
            # Suorita haku
            $query = DB::preparedQuery("
                SELECT training_program.hashid,
                  training_program.program_name,
                  training_program.startdate,
                  training_program.enddate,
                  COUNT(DISTINCT training_program_schedule.id) AS workout_count
                FROM training_program
                LEFT JOIN training_program_schedule ON
                  training_program_schedule.training_programid = training_program.id
                LEFT JOIN template ON
                  template.id = training_program_schedule.templateid
                WHERE training_program.userid=:userid{$where}
                GROUP BY training_program.id
                ORDER BY training_program.startdate,
                  training_program.program_name,
                  training_program.id
                LIMIT 10000
                ",$params
            );
            $numrows = DB::numRows($query);
            if ($numrows > 0) {
                if (!isset($count)) {
                    $count = $numrows-$pos;
                }
                
                if ($count > 0) {
                    if ($pos > 0) {
                        DB::dataSeek($query,$pos);
                    }
                    
                    $c = 0;
                    while ($row = DB::fetchAssoc($query)) {
                        $result["list"][] = $row;
                        if (++$c >= $count) {
                            break;
                        }
                    }
                }
                DB::freeResult($query);
                
                $result["totalCount"] = $numrows;
            }
            
            return $result;
        }
    }